﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Collections
{
  public static class IEnumerableExtensions
  {
    public static CollectionDifference<T, T> Compare<T>(this IEnumerable<T> left, IEnumerable<T> right)
    {
      return Compare(left, right, (x, y) => x.Equals(y));
    }

    public static CollectionDifference<T, TRight> Compare<T, TRight>(this IEnumerable<T> left, IEnumerable<TRight> right, Func<T, TRight, bool> isEqual)
    {
      return Compare(left, right, isEqual, isEqual);
    }
    
    public static CollectionDifference<TLeft, TRight> Compare<TLeft,TRight>(this IEnumerable<TLeft> leftList, IEnumerable<TRight> rightList, Func<TLeft,TRight,bool> isEqual, Func<TLeft,TRight,bool> isSame)
    {
      CollectionDifference<TLeft, TRight> results = new CollectionDifference<TLeft, TRight>();

      results.OnlyInLeftList.AddRange(leftList.Where(x => rightList.Count(y => isSame(x, y)) == 0));
      results.OnlyInRightList.AddRange(rightList.Where(x => leftList.Count(y => isSame(y, x)) == 0));

      foreach (TLeft left in leftList)
      {
        if (rightList.Count(x => isSame(left, x)) == 0)
          continue;

        TRight right = rightList.First(x => isSame(left, x));

        if (!isEqual(left, right))
          results.Different.Add(left, right);
        else
          results.Equal.Add(left, right);
      }
      return results;
    }
  }
}
